package com.example.erat.service.impl;

import com.example.erat.dto.ClassDTO;
import com.example.erat.dto.StudentDTO;
import com.example.erat.entity.ClassEntity;
import com.example.erat.entity.Student;
import com.example.erat.exception.BusinessException;
import com.example.erat.repository.ClassRepository;
import com.example.erat.repository.StudentRepository;
import com.example.erat.service.ClassService;
import com.example.erat.util.ExcelUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 班级服务实现
 */
@Slf4j
@Service
public class ClassServiceImpl implements ClassService {

    @Autowired
    private ClassRepository classRepository;
    
    @Autowired
    private StudentRepository studentRepository;

    @Override
    @Transactional
    public ClassDTO createClass(ClassDTO classDTO) {
        // 检查班级名称是否已存在
        if (classRepository.existsByName(classDTO.getName())) {
            throw new BusinessException("班级名称已存在");
        }
        
        ClassEntity classEntity = new ClassEntity();
        BeanUtils.copyProperties(classDTO, classEntity);
        
        ClassEntity savedClass = classRepository.save(classEntity);
        
        ClassDTO result = new ClassDTO();
        BeanUtils.copyProperties(savedClass, result);
        result.setStudentCount(0);
        
        log.info("创建班级成功: {}", result.getName());
        return result;
    }

    @Override
    @Transactional
    public ClassDTO updateClass(ClassDTO classDTO) {
        // 检查班级是否存在
        ClassEntity classEntity = classRepository.findById(classDTO.getId())
                .orElseThrow(() -> new BusinessException("班级不存在"));
        
        // 检查班级名称是否已存在（如果修改了名称）
        if (!classEntity.getName().equals(classDTO.getName()) && 
            classRepository.existsByName(classDTO.getName())) {
            throw new BusinessException("班级名称已存在");
        }
        
        // 更新班级信息
        classEntity.setName(classDTO.getName());
        classEntity.setGrade(classDTO.getGrade());
        classEntity.setMajor(classDTO.getMajor());
        classEntity.setDescription(classDTO.getDescription());
        
        ClassEntity updatedClass = classRepository.save(classEntity);
        
        ClassDTO result = new ClassDTO();
        BeanUtils.copyProperties(updatedClass, result);
        result.setStudentCount(updatedClass.getStudents().size());
        
        log.info("更新班级成功: {}", result.getName());
        return result;
    }

    @Override
    @Transactional
    public void deleteClass(Long id) {
        // 检查班级是否存在
        ClassEntity classEntity = classRepository.findById(id)
                .orElseThrow(() -> new BusinessException("班级不存在"));
        
        // 删除班级（级联删除学生）
        classRepository.delete(classEntity);
        
        log.info("删除班级成功: {}", classEntity.getName());
    }

    @Override
    public ClassDTO getClassById(Long id) {
        // 检查班级是否存在
        ClassEntity classEntity = classRepository.findById(id)
                .orElseThrow(() -> new BusinessException("班级不存在"));
        
        ClassDTO result = new ClassDTO();
        BeanUtils.copyProperties(classEntity, result);
        result.setStudentCount(classEntity.getStudents().size());
        
        // 转换学生列表
        List<StudentDTO> students = classEntity.getStudents().stream()
                .map(this::convertToStudentDTO)
                .collect(Collectors.toList());
        result.setStudents(students);
        
        return result;
    }

    @Override
    public List<ClassDTO> listClasses() {
        List<ClassEntity> classes = classRepository.findAll();
        
        return classes.stream()
                .map(classEntity -> {
                    ClassDTO dto = new ClassDTO();
                    BeanUtils.copyProperties(classEntity, dto);
                    dto.setStudentCount(classEntity.getStudents().size());
                    return dto;
                })
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public List<StudentDTO> importStudents(Long classId, MultipartFile file) {
        // 检查班级是否存在
        ClassEntity classEntity = classRepository.findById(classId)
                .orElseThrow(() -> new BusinessException("班级不存在"));
        
        // 解析Excel文件
        List<StudentDTO> studentDTOs = ExcelUtil.importStudents(file);
        if (studentDTOs.isEmpty()) {
            throw new BusinessException("Excel文件中没有有效的学生数据");
        }
        
        List<StudentDTO> importedStudents = new ArrayList<>();
        
        // 批量保存学生
        for (StudentDTO studentDTO : studentDTOs) {
            // 检查学号是否已存在
            Student existingStudent = studentRepository.findByStudentId(studentDTO.getStudentId());
            if (existingStudent != null) {
                log.warn("学号为{}的学生已存在，跳过", studentDTO.getStudentId());
                continue;
            }
            
            // 创建新学生
            Student student = new Student();
            student.setStudentId(studentDTO.getStudentId());
            student.setName(studentDTO.getName());
            student.setGrade(studentDTO.getGrade());
            student.setMajor(studentDTO.getMajor());
            student.setClassEntity(classEntity);
            
            Student savedStudent = studentRepository.save(student);
            
            // 转换为DTO返回
            StudentDTO savedDTO = convertToStudentDTO(savedStudent);
            importedStudents.add(savedDTO);
        }
        
        log.info("导入学生成功，共导入{}名学生", importedStudents.size());
        return importedStudents;
    }

    @Override
    @Transactional
    public StudentDTO addStudent(Long classId, StudentDTO studentDTO) {
        // 检查班级是否存在
        ClassEntity classEntity = classRepository.findById(classId)
                .orElseThrow(() -> new BusinessException("班级不存在"));
        
        // 检查学号是否已存在
        if (studentRepository.existsByStudentId(studentDTO.getStudentId())) {
            throw new BusinessException("学号已存在");
        }
        
        // 创建新学生
        Student student = new Student();
        student.setStudentId(studentDTO.getStudentId());
        student.setName(studentDTO.getName());
        student.setGrade(studentDTO.getGrade());
        student.setMajor(studentDTO.getMajor());
        student.setClassEntity(classEntity);
        
        Student savedStudent = studentRepository.save(student);
        
        log.info("添加学生成功: {}", savedStudent.getName());
        return convertToStudentDTO(savedStudent);
    }

    @Override
    @Transactional
    public void removeStudent(Long classId, Long studentId) {
        // 检查班级是否存在
        ClassEntity classEntity = classRepository.findById(classId)
                .orElseThrow(() -> new BusinessException("班级不存在"));
        
        // 检查学生是否存在
        Student student = studentRepository.findById(studentId)
                .orElseThrow(() -> new BusinessException("学生不存在"));
        
        // 检查学生是否属于该班级
        if (!student.getClassEntity().getId().equals(classId)) {
            throw new BusinessException("该学生不属于指定班级");
        }
        
        // 删除学生
        studentRepository.delete(student);
        
        log.info("删除学生成功: {}", student.getName());
    }

    @Override
    public List<StudentDTO> listClassStudents(Long classId) {
        // 检查班级是否存在
        Optional<ClassEntity> classOpt = classRepository.findById(classId);
        if (!classOpt.isPresent()) {
            throw new BusinessException("班级不存在");
        }
        
        List<Student> students = studentRepository.findByClassEntityId(classId);
        
        return students.stream()
                .map(this::convertToStudentDTO)
                .collect(Collectors.toList());
    }
    
    /**
     * 将Student实体转换为StudentDTO
     */
    private StudentDTO convertToStudentDTO(Student student) {
        StudentDTO dto = new StudentDTO();
        BeanUtils.copyProperties(student, dto);
        
        // 设置班级相关信息
        if (student.getClassEntity() != null) {
            dto.setClassId(student.getClassEntity().getId());
            dto.setClassName(student.getClassEntity().getName());
        }
        
        return dto;
    }
} 